Conversation
There was a problem hiding this comment.
Pull request overview
Adds Vitest coverage support and introduces new unit tests to increase runtime coverage for the JavaScript SDK’s Catcher and validation utilities.
Changes:
- Added comprehensive tests for
Catcherbehavior (delivery, dedupe, context/user handling, global handlers, addons). - Added focused tests for
src/utils/validation.tshelpers. - Added a
test:coveragescript and the@vitest/coverage-v8dependency to enable coverage reporting.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| yarn.lock | Locks new coverage-related dependencies (notably @vitest/coverage-v8). |
| packages/javascript/package.json | Adds test:coverage and @vitest/coverage-v8 dev dependency. |
| packages/javascript/tests/utils/validation.test.ts | New tests for validation helpers. |
| packages/javascript/tests/catcher.test.ts | New tests covering Catcher end-to-end behavior using a mocked transport. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { validateUser, validateContext, isValidEventPayload, isValidBreadcrumb } from '../../src/utils/validation'; | ||
|
|
||
| // Suppress console output produced by log() calls inside validation failures. | ||
| vi.mock('../src/utils/log', () => ({ default: vi.fn() })); |
There was a problem hiding this comment.
vi.mock path is incorrect from tests/utils/validation.test.ts. validation.ts imports log from ./log (resolves to src/utils/log.ts), but this test is mocking ../src/utils/log (which would resolve under tests/src/...). Update the mock to target the actual module (e.g. ../../src/utils/log).
| vi.mock('../src/utils/log', () => ({ default: vi.fn() })); | |
| vi.mock('../../src/utils/log', () => ({ default: vi.fn() })); |
| it('should accept a plain string as a shorthand for the token', async () => { | ||
| const sendSpy = vi.fn().mockResolvedValue(undefined); | ||
| const transport: Transport = { send: sendSpy }; | ||
|
|
||
| const hawk = new Catcher({ |
There was a problem hiding this comment.
Test name doesn't match what's being exercised: this case constructs new Catcher({ token: TEST_TOKEN, ... }) (settings object), not new Catcher(TEST_TOKEN) (string shorthand). Rename the test (or change the setup) so the description matches the behavior under test.
| it('should log a warning when transport.send rejects', async () => { | ||
| const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); | ||
| const transport: Transport = { | ||
| send: vi.fn().mockRejectedValue(new Error('network error')), | ||
| }; |
There was a problem hiding this comment.
The description says "log a warning", but the code under test logs with type 'error' (and this test spies on console.error). Rename the test to reflect the actual behavior.
There was a problem hiding this comment.
All cases that checked log effect have been redone: now they check that catcher handles inner Errors.
| // The Catcher's primary responsibility: capture errors and forward them to | ||
| // the configured transport with identifying metadata. | ||
| describe('error delivery', () => { | ||
| it('should deliver an Error instance via transport with matching title', async () => { |
There was a problem hiding this comment.
what does it mean "with matching title"?
There was a problem hiding this comment.
Meaning we expect that HawkJavaScriptEvent.title same as send Error.message
There was a problem hiding this comment.
this statement is not clear. Make a test case name more straightforward.
What to you want to test? "error should be sent" or "payload title should be composed from error message"?
| it('should ignore setUser when called with null', async () => { | ||
| const { sendSpy, transport } = createTransport(); | ||
| const hawk = createCatcher(transport); | ||
|
|
||
| hawk.setUser({ id: 'valid' }); | ||
| hawk.setUser(null as never); | ||
| hawk.send(new Error('e')); | ||
| await wait(); | ||
|
|
||
| expect(getLastPayload(sendSpy).user?.id).toBe('valid'); | ||
| }); |
| it('should construct without error when given a bare token string', () => { | ||
| const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); | ||
| const addELSpy = vi.spyOn(window, 'addEventListener').mockImplementation(() => undefined); | ||
|
|
||
| expect(() => new Catcher(TEST_TOKEN)).not.toThrow(); | ||
|
|
||
| addELSpy.mockRestore(); | ||
| consoleSpy.mockRestore(); | ||
| }); |
There was a problem hiding this comment.
duplicates "should accept a plain string as a shorthand for the token"
There was a problem hiding this comment.
In general, it would be better to call this case this way.
Fixed.
| }); | ||
|
|
||
| // ── Transport failure ───────────────────────────────────────────────────── | ||
| describe('transport failure', () => { |
There was a problem hiding this comment.
Moved to catcher.transport.test.ts.
|
|
||
| // ── Transport failure ───────────────────────────────────────────────────── | ||
| describe('transport failure', () => { | ||
| it('should log a warning when transport.send rejects', async () => { |
There was a problem hiding this comment.
This test checks that in this case we will leave an error log (in fact the only effect in this case)
There was a problem hiding this comment.
Redone case by checking if call does not throw.
| errorSpy.mockRestore(); | ||
| }); | ||
|
|
||
| it('should log a warning when beforeSend throws unexpectedly', async () => { |
There was a problem hiding this comment.
the case is not clear. Why it throws?
There was a problem hiding this comment.
Why it throws?
Since we receive beforeSend from outside, it may probably throw an error.
This test checks that in this case we will leave an error log (in fact the only effect in this case)
There was a problem hiding this comment.
Redone case by checking if call does not throw.
| // ── Environment addons ──────────────────────────────────────────────────── | ||
| // | ||
| // Browser-specific data collected from window (URL, GET params, debug info). | ||
| describe('environment addons', () => { |
There was a problem hiding this comment.
move to a separate file, like "browser-addons.test.ts"
There was a problem hiding this comment.
Moved to catcher.addons.test.ts.
Covering with tests components in
@hawk.so/javascript:catcher.tsutils/validation.tsCoverage report: